package top.byfree.jbyan.saber.dao

import org.ktorm.dsl.*
import org.ktorm.schema.ColumnDeclaring
import org.springframework.stereotype.Component
import top.byfree.jbyan.saber.bean.*
import top.byfree.jbyan.saber.bean.dto.FilterUserDto
import top.byfree.jbyan.saber.bean.pojo.Perm
import top.byfree.jbyan.saber.bean.pojo.Role
import top.byfree.jbyan.saber.bean.pojo.User
import top.byfree.jbyan.saber.bean.vo.permVoCol
import top.byfree.jbyan.saber.bean.vo.roleVoCol
import top.byfree.jbyan.saber.common.BaseDao
import top.byfree.jbyan.saber.common.coverOrderBy

/**
 * 用户数据处理层
 *
 * @author jbyan
 * @since 21/3/2024
 */
@Component
open class UserDao : BaseDao<User, Users>(Users) {

    /* 根据用户id获取角色列表 */
    fun findRoles(userId: String): MutableList<Role> {
        val roles = database.from(UserRoles)
            .leftJoin(Roles, on = UserRoles.roleId eq Roles.roleId)
            .select(roleVoCol)
            .where {
                (UserRoles.userId eq userId) and
                        (Roles.isDelete eq IS_DELETE_NO) and
                        (Roles.status eq ROLE_STATUS_NORMAL)
            }.map(Roles::createEntity).toMutableList()

        val all = roles.map { it.roleKey }.toList().contains("*")

        // 检索角色下所有子角色
        val child = roles.filter { it.roleKey.contains("*") }.map { it.roleKey.replace("*", "%") }

        if (!all && child.isEmpty()) {
            return roles
        }

        val superRoles = database.from(Roles)
            .select(roleVoCol)
            .where {
                val basic = (Roles.isDelete eq IS_DELETE_NO) and (Roles.status eq PERM_STATUS_NORMAL)
                val condition = mutableListOf<ColumnDeclaring<Boolean>>()
                child.forEach {
                    condition += Roles.roleKey like it
                }
                if (all) basic
                else basic and condition.reduce { a, b -> a or b }
            }.map(Roles::createEntity).toMutableList()

        superRoles.addAll(roles.filter { !it.roleKey.contains("*") })

        return superRoles
    }


    /* 根据用户Id获取权限列表 */
    fun findPerms(userId: String): Iterable<Perm> {
        val roles = findRoles(userId).map { it.roleId }

        if (roles.isEmpty()) {
            return emptyList()
        }

        val perms = database.from(RolePerms)
            .leftJoin(Perms, on = Perms.permId eq RolePerms.permId)
            .select(permVoCol)
            .where {
                (Perms.isDelete eq IS_DELETE_NO) and
                        (Perms.status eq PERM_STATUS_NORMAL) and
                        (RolePerms.roleId inList roles)
            }.map(Perms::createEntity).toMutableList()

        // 拥有*权限代表拥有最高权限
        val all = perms.map { it.permKey }.toList().contains("*")

        // 检索所有权限下的子权限
        val child = perms.filter { it.permKey.contains("*") }
            .map { it.permKey.replace("*", "%") }

        // 当不具有父级权限时直接返回
        if (!all && child.isEmpty()) {
            return perms
        }

        val superPerms = database.from(Perms)
            .select(permVoCol)
            .where {
                val basic = (Perms.isDelete eq IS_DELETE_NO) and (Perms.status eq PERM_STATUS_NORMAL)
                val condition = mutableListOf<ColumnDeclaring<Boolean>>()
                child.forEach {
                    condition += Perms.permKey like it
                }
                if (all) basic
                else basic and condition.reduce { a, b -> a or b }
            }.map(Perms::createEntity).toMutableList()

        superPerms.addAll(perms.filter { !it.permKey.contains("*") })

        return superPerms
    }

    /* 逻辑删除用户 */
    fun logicDelete(userList: MutableList<String>) =
        database.update(Users) {
            set(it.isDelete, IS_DELETE_YES)

            where {
                it.userId inList userList
            }
        } > 0

    /* 条件查询用户列表 */
    fun filter(filterUserDto: FilterUserDto): Query {
        val (username, nickname, email, status, gmtCreateStart, gmtCreateEnd, createBy, modifyBy, orderBy) = filterUserDto

        val query = database.from(Users)
            .select()
            .whereWithConditions { cl ->
                if (!username.isNullOrBlank()) {
                    cl += Users.username like "%$username%"
                }
                if (!nickname.isNullOrBlank()) {
                    cl += Users.nickname like "%$nickname%"
                }
                if (!email.isNullOrBlank()) {
                    cl += Users.email like "%$email%"
                }
                status?.let { cl += Users.status eq status }
                gmtCreateStart?.let {
                    cl += Users.gmtCreate gte it
                }
                gmtCreateEnd?.let {
                    cl += Users.gmtCreate lte it
                }
                if (!createBy.isNullOrBlank()) {
                    cl += Users.createBy like "%$createBy%"
                }
                if (!modifyBy.isNullOrBlank()) {
                    cl += Users.modifyBy like "%$modifyBy%"
                }
            }
        val coverOrderBy = Users.coverOrderBy(orderBy)
        // 添加排序
        return coverOrderBy?.let {
            query.orderBy(coverOrderBy)
        } ?: query
    }
}